using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using BloxGin.Cameras;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using BloxGin;

namespace BloxGame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        World world;

        BloxGin.World.Sun sun;

        Object camera;

        public ICamera Camera
        {
            get
            {
                return (ICamera)camera;
            }

        }
        
        BloxGin.Graphics.VertexBlock[] vertices;

        public BloxGin.Input.InputHelper input;

        BloxGame.Player.Player player;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            camera = new FirstPersonCamera(this);

            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferredBackBufferWidth = 1280;
           // graphics.ToggleFullScreen();

            //camera.Speed = 0.5f;
            this.Components.Add(camera as GameComponent);

            input = new BloxGin.Input.InputHelper(this);
            this.Components.Add(input);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            vertices = new BloxGin.Graphics.VertexBlock[3];
            vertices[0] = new BloxGin.Graphics.VertexBlock(new BloxGin.Graphics.ByteVector4(0, 0, 0),Vector3.Zero, new HalfVector2(0, 0));

            
           //buffer =  new VertexBuffer(GraphicsDevice,typeof(Vertex
          //  graphics.SynchronizeWithVerticalRetrace = false;

          

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            world = new World(GraphicsDevice,Camera,Content.Load<Texture2D>("terrain"));

            Vector3 startPosition = Camera.Position;
            startPosition.Y = 125;
            player = new Player.Player(this, world, startPosition);


            GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;

            sun = new BloxGin.World.Sun();
            sun.LoadContent(Content);
            //GraphicsDevice.SamplerStates[0].AddressV = TextureAddressMode.Clamp;
            
          //  GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
            

         // GraphicsDevice.RasterizerState = RasterizerState.CullNone;
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            input.Begin();

            player.Update(gameTime);

            world.Update(gameTime,sun.position);
            sun.Update(gameTime, Camera);

            if(input.IsNewKeyPress(Keys.C))
            {
               /* Vector3 position = Camera.Position;
                if (camera is FreeMouseCam)
                {
                    
                    this.Components.Remove(camera as GameComponent);
                    camera = new FirstPersonCamera(this);
                   
                    this.Components.Add(camera as GameComponent);
                    (camera as GameComponent).Initialize();
                }
                else
                {
                    this.Components.Remove(camera as GameComponent);
                    camera = new FreeMouseCam(this);
                  
                    this.Components.Add(camera as GameComponent);
                }
                Camera.Position = position;
                */
                camera = new FirstPersonCamera(this);
                (camera as GameComponent).Initialize();
                (camera as GameComponent).Update(gameTime);
            }
      

            input.End();

           
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            sun.Draw(GraphicsDevice, Camera.View, Camera.Projection, spriteBatch);

            world.Draw(gameTime);

            player.Draw(gameTime);

            base.Draw(gameTime);
        }
    }
}
